home *** CD-ROM | disk | FTP | other *** search
/ The World's Largest Collection of Windows Software / The World's Largest Collection of Windows Software - Disc 1.iso / connect / _j2 / wvnsc926 / rcs / headarry.c < prev    next >
C/C++ Source or Header  |  1994-09-21  |  22KB  |  962 lines

  1. head     1.9;
  2. branch   ;
  3. access   ;
  4. symbols  V80:1.5;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.9
  10. date     94.09.18.00.45.40;  author jcooper;  state Exp;
  11. branches ;
  12. next     1.8;
  13.  
  14. 1.8
  15. date     94.01.21.23.17.18;  author rushing;  state Exp;
  16. branches ;
  17. next     1.7;
  18.  
  19. 1.7
  20. date     93.12.08.01.27.21;  author rushing;  state Exp;
  21. branches ;
  22. next     1.6;
  23.  
  24. 1.6
  25. date     93.06.25.20.44.45;  author dumoulin;  state Exp;
  26. branches ;
  27. next     1.5;
  28.  
  29. 1.5
  30. date     93.06.10.18.29.34;  author rushing;  state Exp;
  31. branches ;
  32. next     1.4;
  33.  
  34. 1.4
  35. date     93.06.08.19.41.56;  author rushing;  state Exp;
  36. branches ;
  37. next     1.3;
  38.  
  39. 1.3
  40. date     93.06.05.03.18.25;  author rushing;  state Exp;
  41. branches ;
  42. next     1.2;
  43.  
  44. 1.2
  45. date     93.06.04.16.46.44;  author rushing;  state Exp;
  46. branches ;
  47. next     1.1;
  48.  
  49. 1.1
  50. date     93.06.01.18.15.12;  author rushing;  state Exp;
  51. branches ;
  52. next     ;
  53.  
  54.  
  55. desc
  56. @routines for handling the header and thread index arrays
  57. @
  58.  
  59.  
  60. 1.9
  61. log
  62. @rearranged headers to allow use of precompiled headers
  63. @
  64. text
  65. @
  66. /* headarry.c
  67.  * author: Sam Rushing
  68.  * $Id: headarry.c 1.8 1994/01/21 23:17:18 rushing Exp $
  69.  * $Log: headarry.c $
  70.  * Revision 1.8  1994/01/21  23:17:18  rushing
  71.  * Documented the thread sort algorithm.
  72.  *
  73.  * Revision 1.7  1993/12/08  01:27:21  rushing
  74.  * new version box and cr lf consistency
  75.  * *
  76.  * routines for handling the array of header information
  77.  *
  78.  * Revision 1.6  1993/06/25  20:44:45  dumoulin
  79.  * Change dates from strings to Posix standard date formats
  80.  *
  81.  * Revision 1.5  1993/06/10  18:29:34  rushing
  82.  * added set_index_to_identity to prepare for writing article ranges
  83.  *
  84.  * Revision 1.4  1993/06/08  19:41:56  rushing
  85.  * changes to support Sort... menu
  86.  *
  87.  * Revision 1.3  1993/06/05  03:18:25  rushing
  88.  * primitive functional threading.
  89.  *
  90.  * Revision 1.2  1993/06/04  16:46:44  rushing
  91.  * stable version of shellsort
  92.  *
  93.  * Revision 1.1  1993/06/01  18:15:12  rushing
  94.  * Initial revision
  95.  *
  96.  *
  97.  */ 
  98.  
  99. #include <windows.h>
  100. #include <windowsx.h>
  101. #include "wvglob.h"
  102. #include "winvn.h"
  103. #pragma hdrstop
  104.  
  105. /* The header and thread arrays are set up as follows:
  106.  * When we allocate space for the TypHeader array, we leave room for a
  107.  * pointer at the very front of that space, which will either indicate 
  108.  * that there is no thread index array (== NULL) or will point to that
  109.  * array.  Since windows can move both of these arrays around, this
  110.  * slot is updated whenever lock_headers is called.
  111.  * 
  112.  * After initialize_header_array is called, this sequence of
  113.  * operations can be used to access the header array:
  114.  * 1. header_p headers = lock_headers (header_handle, thread_handle);
  115.  * 2. header_elt (headers, index);
  116.  * 3. unlock_headers (header_handle, thread_handle);
  117.  *
  118.  * The thread_index array is an array of longs, each an index into the
  119.  * the real header array.  If thread_index is allocated and filled,
  120.  * header_elt will indirect through it.  Sorting the array of indices
  121.  * will sort the headers accordingly.
  122.  */ 
  123.  
  124. /* globals, yuck! */
  125. header_p g_headers;
  126. thread_array g_index, g_parent, g_parsort;
  127. long g_length;
  128.  
  129. /* lock the headers and the thread index array in memory for access */
  130.  
  131. header_p
  132. lock_headers (HANDLE header_handle,HANDLE thread_handle)
  133. {
  134.   thread_array_p indirect;
  135.   header_p headers;
  136.  
  137.   /* lock the header array in position */
  138.   indirect = (thread_array_p) GlobalLock (header_handle);
  139.  
  140.   headers = (header_p) ((char_p) indirect + sizeof (char_p));
  141.   
  142.   /* if we've a valid thread_handle, lock the thread_array, too */
  143.   if (thread_handle) {
  144.     *indirect = (thread_array) GlobalLock (thread_handle);
  145.   }
  146.   else
  147.     *indirect = NULL;
  148.   
  149.   return (headers);
  150. }
  151.  
  152. /* unlock the headers and thread index array */
  153.  
  154. void
  155. unlock_headers (HANDLE header_handle, HANDLE thread_handle)
  156. {
  157.   GlobalUnlock (header_handle);
  158.   if (thread_handle)
  159.     GlobalUnlock (thread_handle);
  160. }
  161.  
  162.  
  163. /* return the header memory to windows */
  164.  
  165. void
  166. free_headers (HANDLE header_handle, HANDLE thread_handle)
  167. {
  168.   GlobalFree (header_handle);
  169.   if (thread_handle)
  170.     GlobalFree (thread_handle);
  171. }
  172.  
  173.  
  174. void
  175. set_index_to_identity (HANDLE header_handle, HANDLE thread_handle, long length)
  176. {
  177.   long i;
  178.   header_p headers;
  179.   thread_array thread_index;
  180.   thread_array_p thread_index_p;
  181.  
  182.   headers = lock_headers (header_handle, thread_handle);
  183.  
  184.   if (thread_handle) {
  185.     thread_index_p  = (thread_array_p) ((char_p) headers - sizeof (char_p));
  186.     thread_index = *thread_index_p;
  187.     
  188.     /* Initialize with identity */
  189.     for (i=0; i <length ; i++)
  190.       thread_index[i] = i;
  191.   }
  192. }
  193.  
  194.  
  195. /* set up the header array, and possibly the thread index array */
  196.  
  197. void
  198. initialize_header_array (HANDLE header_handle, HANDLE thread_handle, long length)
  199. {
  200.   long i;
  201.   header_p headers;
  202.   thread_array thread_index;
  203.   thread_array_p thread_index_p;
  204.  
  205.   headers = lock_headers (header_handle, thread_handle);
  206.  
  207.   if (thread_handle) {
  208.     thread_index_p  = (thread_array_p) ((char_p) headers - sizeof (char_p));
  209.     thread_index = *thread_index_p;
  210.     
  211.     /* Initialize with identity */
  212.     for (i=0; i <length ; i++)
  213.       thread_index[i] = i;
  214.   }
  215.  
  216.   for (i=0; i < length ; i++) {
  217.     headers[i].Seen = (char) 0;
  218.     headers[i].Selected = (char) 0;
  219.     headers[i].number = 0;
  220.     headers[i].thread_depth = 0;
  221.     headers[i].lines = 0;
  222.     headers[i].date =  0;
  223.     headers[i].subject[0] = (char) 0;
  224.     headers[i].from[0] = (char) 0;
  225.     headers[i].message_id[0] = (char) 0;
  226.     headers[i].references[0] = (char) 0;
  227.     headers[i].ArtDoc = NULL;
  228.   }
  229.   unlock_headers (header_handle, thread_handle);
  230. }
  231.  
  232. /* Use this routine to get at an element of the header array - it  */
  233. /* will automatically indirect through the thread index array if it's */
  234. /* there. */
  235.  
  236. header_p
  237. header_elt (header_p headers, long index)
  238. {
  239.   
  240.   thread_array thread_index;
  241.   thread_index  = *((thread_array_p) ((char_p) headers - sizeof (char_p)));  
  242.  
  243.   if (thread_index) {
  244.     return (&(headers[thread_index[index]]));
  245.   }
  246.   else
  247.     return (&(headers[index]));
  248. }
  249.       
  250. int
  251. compare_artnum (header_p headers,
  252.         long elem1, long elem2)
  253. {
  254.   long e1,e2;
  255.   e1=headers[elem1].number;
  256.   e2=headers[elem2].number;
  257.   if (e1 == e2)
  258.     return 0;
  259.   else if (e1 < e2)
  260.     return -1;
  261.   else
  262.     return 1;
  263. }
  264.  
  265.       
  266. int
  267. compare_lines (header_p headers,
  268.         long elem1, long elem2)
  269. {
  270.   long e1,e2;
  271.   e1=headers[elem1].lines;
  272.   e2=headers[elem2].lines;
  273.   if (e1 == e2)
  274.     return 0;
  275.   else if (e1 < e2)
  276.     return -1;
  277.   else
  278.     return 1;
  279. }
  280.  
  281. int  
  282. compare_message_id (header_p headers,
  283.             long elem1, long elem2)
  284. {
  285.   return strcmp (headers[elem1].message_id , headers[elem2].message_id);
  286. }
  287.  
  288.   
  289. int
  290. compare_subject (header_p headers,
  291.          long elem1, long elem2)
  292. {
  293.   return stricmp (headers[elem1].subject , headers[elem2].subject);
  294. }
  295.  
  296. int
  297. compare_from (header_p headers,
  298.          long elem1, long elem2)
  299. {
  300.   return stricmp (headers[elem1].from , headers[elem2].from);
  301. }
  302.  
  303. int
  304. compare_date (header_p headers,
  305.           long elem1, long elem2)
  306. {
  307.   long e1,e2;
  308.   e1=headers[elem1].date;
  309.   e2=headers[elem2].date;
  310.   if (e1 == e2)
  311.     return 0;
  312.   else if (e1 < e2)
  313.     return -1;
  314.   else
  315.     return 1;
  316. }
  317.  
  318. /* this is the shell sort taken from shellsor.c and modified for */
  319. /* threading purposes... The extra comparison is to make the sort */
  320. /* stable w.r.t. article number */
  321.  
  322. void
  323. shell_sort_index_array (header_p headers,
  324.             thread_array index,
  325.             long nElements,
  326.             int (*compare) (header_p headers,
  327.                     long elem1,
  328.                     long elem2))
  329. {
  330. #define STRIDE_FACTOR 3
  331.   int c, d, stride;
  332.   int found;
  333.  
  334.   stride = 1;
  335.   while (stride <= nElements)
  336.     stride = stride * STRIDE_FACTOR + 1;
  337.  
  338.   while (stride > (STRIDE_FACTOR - 1))
  339.     {
  340.       stride = stride / STRIDE_FACTOR;
  341.       for (c = stride; c < nElements; c++)
  342.     {
  343.       found = 0;
  344.       d = c - stride;
  345.       while ((d >= 0) && !found)
  346.         {
  347.           int comp = compare (headers, index[d + stride], index[d]);
  348.           if ((comp < 0) ||
  349.           ((comp == 0) &&
  350.            (compare_artnum (headers, index[d + stride], index[d]) < 0)))
  351.         {
  352.           long tmp = index[d];
  353.           index[d] = index[d+stride];
  354.           index[d+stride] = tmp;
  355.           d -= stride;
  356.         }
  357.           else
  358.         {
  359.           found = 1;
  360.         }
  361.         }
  362.     }
  363.     }
  364. }
  365.  
  366.  
  367. void
  368. shell_sort_parent_array (thread_array index,
  369.              thread_array parents,
  370.              long n)
  371. {
  372. #define STRIDE_FACTOR 3
  373.   int c, d, stride;
  374.   int found;
  375.  
  376.   stride = 1;
  377.   while (stride <= n)
  378.     stride = stride * STRIDE_FACTOR + 1;
  379.  
  380.   while (stride > (STRIDE_FACTOR - 1))
  381.     {
  382.       stride = stride / STRIDE_FACTOR;
  383.       for (c = stride; c < n ; c++)
  384.     {
  385.       found = 0;
  386.       d = c - stride;
  387.       while ((d >= 0) && !found)
  388.         {
  389.           long p1 = parents[index[d+stride]];
  390.           long p2 = parents[index[d]];
  391.  
  392.           if ((p1 < p2) || ((p1 == p2) && (index[d+stride] > index[d])))
  393.         {
  394.           long tmp = index[d];
  395.           index[d] = index[d+stride];
  396.           index[d+stride] = tmp;
  397.           d -= stride;
  398.         }
  399.           else
  400.         {
  401.           found = 1;
  402.         }
  403.         }
  404.     }
  405.     }
  406. }
  407.  
  408. long
  409. bsearch_parsort_table (thread_array parsort,
  410.                thread_array parents,
  411.                long looking_for,
  412.                long n)
  413. {
  414.   long p;  
  415.   long high = n;
  416.   long low = 0;
  417.   
  418.   while ((high - low) > 1) {
  419.     p = (high + low) / 2;
  420.     if (looking_for <= parents[parsort[p-1]])
  421.       high = p;
  422.     else
  423.       low = p;
  424.   }
  425.   if (looking_for == parents[parsort[high-1]])
  426.     return (high-1);
  427.   else
  428.     return -1;
  429. }
  430.  
  431.  
  432. long
  433. bsearch_mid_table (header_p headers,
  434.            thread_array index, /* sorted index */
  435.            char * mid,    /* message_id we're looking for */
  436.            long n)
  437. {
  438.   long p;  
  439.   long high = n;
  440.   long low = 0;
  441.   
  442.   while ((high - low) > 1) {
  443.     p = (high + low) / 2;
  444.     if (strcmp (mid, headers[index[p-1]].message_id) <= 0)
  445.       high = p;
  446.     else
  447.       low = p;
  448.   }
  449.   if (strcmp (mid, headers[index[high-1]].message_id) == 0)
  450.     return (high-1);
  451.   else
  452.     return -1;
  453. }
  454.  
  455.  
  456. long
  457. thread_sort (long root_index, long start, long end, int depth)
  458. {
  459.   long j;
  460.   long num_children = 0;
  461.   long child_start;
  462.  
  463.   if (start == end)
  464.     return end;
  465.   else {
  466.     /* find the children of this node, pack them in the bottom */
  467.  
  468.     /* this will find the first child in the sorted table */
  469.     child_start = bsearch_parsort_table (g_parsort,
  470.                      g_parent,
  471.                      root_index,
  472.                      g_length);
  473.  
  474.     /* for each child, find its index and push on the stack in g_index */
  475.     if (child_start != -1) {
  476.       while ((child_start < g_length) &&
  477.          (g_parent[g_parsort[child_start]] == root_index)) {
  478.     g_index[end-num_children-1] = g_parsort[child_start];
  479.     child_start++;
  480.     num_children++;
  481.       }
  482.     }
  483.     /* no children found */
  484.     else
  485.       return (start);
  486.  
  487.     /* apply sort-me to each of the children */
  488.  
  489.     if (num_children == 0)
  490.       return (start);
  491.  
  492.     for (j = num_children ; j > 0 ; j--) {
  493.       g_index[start] = g_index[end-j];
  494.       g_headers[g_index[start]].thread_depth = (char) depth;
  495.       start = thread_sort (g_index[start], start+1, end-(j-1), depth+1);
  496.     }
  497.     return (start);
  498.   }
  499. }
  500.  
  501.  
  502. /* setup for threading algorithm:
  503.  * 1. allocate an extra thread_array for holding a sorted message-id table
  504.  * 2. using mid_table, allocate and create another table, a map from
  505.  *    article_index->parent_index  
  506.  * 3. sort this table by parent_index (must be a stable sort)
  507.  * 
  508.  * the recursive thread_sort will use these tables to do a stable sort
  509.  * by threads...
  510.  */
  511.  
  512. void
  513. sort_by_threads (HANDLE header_handle, HANDLE thread_handle, long length)
  514. {
  515.   long i;
  516.   header_p headers;
  517.   HANDLE mid_handle, parent_handle;
  518.   thread_array thread_index,mid_table,parent_table;
  519.   
  520.   headers = lock_headers (header_handle, thread_handle);
  521.   thread_index  = *((thread_array_p) ((char_p) headers - sizeof (char_p)));  
  522.  
  523.   if (!thread_index)
  524.     return;
  525.  
  526.   mid_handle = GlobalAlloc (GMEM_MOVEABLE, (long) (sizeof(long) * length));
  527.   if (!mid_handle)
  528.     return;
  529.  
  530.   parent_handle = GlobalAlloc (GMEM_MOVEABLE, (long) (sizeof (long) * length));
  531.   if (!parent_handle) {
  532.     GlobalFree (mid_handle);
  533.     return;
  534.   }
  535.     
  536.   mid_table = (thread_array) GlobalLock (mid_handle);
  537.   parent_table = (thread_array) GlobalLock (parent_handle);
  538.   
  539.   /* create the message_id table */
  540.   for (i=0 ; i < length; i++) mid_table[i]=i;
  541.   shell_sort_index_array (headers, mid_table, length, compare_message_id);
  542.  
  543.   /* create the parent table */
  544.   
  545.   for (i=0 ; i < length; i++) {
  546.     long p = bsearch_mid_table (headers,mid_table,headers[i].references,length);
  547.     parent_table[i] = (p == -1) ? -1 : mid_table[p];
  548.   }
  549.  
  550.   /* clear it so we can debug */
  551.   for (i=0 ; i< length; i++)
  552.     thread_index[i]=0;
  553.  
  554.   /* re-use the mid_table as a sorted parent table */
  555.   for (i=0 ; i< length; i++)
  556.     mid_table[i]=i;
  557.  
  558.   shell_sort_parent_array (mid_table, parent_table, length);
  559.  
  560.   g_headers = headers;
  561.   g_index = thread_index;
  562.   g_parent = parent_table;
  563.   g_parsort = mid_table;
  564.   g_length = length;
  565.  
  566.   thread_sort (-1, 0, length,0);
  567.  
  568.   GlobalFree (parent_handle);
  569.   GlobalFree (mid_handle);
  570. }
  571.  
  572. /*
  573. --------------------------------------------------------------------------
  574.  
  575. Thread sorting algorithm.
  576.  
  577. Here's an example, already threaded, showing the relationship between
  578. parent, child, and original index.
  579.  
  580.  
  581.  
  582. 0   5
  583. 1      2
  584. 2         3
  585. 3      0   
  586. 4   1   
  587. 5      4        
  588.  
  589. On the display, it may look like this:
  590.  
  591. 5   Why my computer is better than yours...
  592. 2     Re: Why my computer is better than yours...
  593. 3       Why my _car_ is better than your computer (was Re: ...)
  594. 0     Re: Why my computer is better than yous...
  595. 1   What's the latest on the Amiga 6000???
  596. 4     What planet are you on ? (was Re: What's the latest...)
  597.  
  598. This shows that articles #2 and #0 are in response to article #5 (yes this can
  599. and does happen), article #4 is in response to #1, etc...
  600.  
  601. This is the parent table.  It answers the question: "what is the index
  602. of my parent".  '*' means root, or 'no' index - either there is no    
  603. parent of this article, or we don't have it.  In the code, '*' == -1.
  604.  
  605.   |--|
  606. 0 |5 |
  607.   |--|
  608. 1 |* | 
  609.   |--|
  610. 2 |5 |
  611.   |--|
  612. 3 |2 |
  613.   |--|
  614. 4 |1 |
  615.   |--|
  616. 5 |* |
  617.   |--|
  618.  
  619. This table was computed by
  620. 1) sorting by Message-ID (by creating 'mid_table') with a shell sort.
  621. 2) use 'mid_table' to find each article's parent (using a binary search),
  622.    thereby creating 'parent_table'.
  623. 3) mid_table's not needed any longer, so we now re-use it as a sorted
  624.    index into parent_table.  More on this later.
  625.  
  626. What we want from thread_sort is for the empty thread_index to hold
  627. an array with these articles indices in the correct order:
  628.                                          
  629. |--|
  630. |5 |
  631. |--|
  632. |2 |
  633. |--|
  634. |3 |
  635. |--|
  636. |0 |
  637. |--|
  638. |1 |
  639. |--|
  640. |4 |
  641. |--|
  642.  
  643. ---------------------------------------------------------------------------
  644. Now, for the actual algorithm.  The work is performed by the recursive
  645. function thread_sort().
  646.  
  647. thread_sort (root_index, start, end, depth) { ... }
  648. (depth is used to keep track of the depth of the recursion)
  649.  
  650. 1) Start with an empty index table.  start = 0 (the beginning of the
  651.    table), and end = length (the length of the table).
  652.  
  653. 2) Find all the children of the current root, (which is '*' to start
  654.    with), and pack them (in order) into the bottom of the table.
  655.    If there are no children, return 'start'.
  656.    If start == end, return 'start'.
  657.  
  658. 3) Now, we will recurse [call thread_root()] for each of these
  659.    children, using the empty portion of thread_index to work with.
  660.    We do this by:
  661.      
  662.    3a) Move child #1 into the top slot.
  663.    3b) calling thread_sort, with
  664.        root_index = child #1
  665.        start = start of the empty portion
  666.        end = end of the empty portion
  667.        depth = depth+1
  668.    3c) After thread_sort() does its magic, it will return a 
  669.        new value for 'start', indicating where the 'work area'
  670.        can start.  thread_sort() may have filled in an arbitrary
  671.        number of slots in this call, but will never overstep the
  672.        free space.  Don't worry, it all works out.  8^)
  673.  
  674.    3d) Go to child #2, repeat 3(a-c), #3, #4, etc...
  675.  
  676. 4) return 'start' (the start of the empty space).
  677.                   
  678. Here's a trace of the algorithm using our example articles.
  679. ---------------------------------------------------------------------------
  680. The number above the stack of boxes indicates the parent that
  681. we're finding the children of.
  682.  
  683.    *                      
  684.   |--|  |--|                                                
  685. 0 |  |  |5 |   5                                            
  686.   |--|  |--|  |--|  |--|                          |--|  |--|
  687. 1 |  |  |  |  |  |  |2 |   2                      |2 |  |2 |
  688.   |--|  |--|  |--|  |--|  |--|  |--|        |--|  |--|  |--|
  689. 2 |  |  |  |  |  |  |  |  |  |  |3 |   3    |3 |  |3 |  |3 |    ==>
  690.   |--|  |--|  |--|  |--|  |--|  |--|  |--|  |--|  |--|  |--|
  691. 3 |  |  |  |  |2 |  |  |  |3 |  |  |  |  |  |  |  |  |  |  |
  692.   |--|  |--|  |--|  |--|  |--|  |--|  |--|  |--|  |--|  |--|
  693. 4 |5 |  |  |  |0 |  |0 |                                |0 |
  694.   |--|  |--|  |--|  |--|                                |--|
  695. 5 |1 |  |1 |                                                
  696.   |--|  |--|                                                
  697.                                                           
  698.  
  699. continued...
  700.                                          
  701.                     |--|                    |--|
  702. 0                   |5 |                    |5 |
  703.               |--|  |--|                    |--|
  704. 1             |2 |  |2 |                    |2 |
  705.               |--|  |--|                    |--|
  706. 2             |3 |  |3 |                    |3 |
  707.   |--|        |--|  |--|                    |--|
  708. 3 |0 |   0    |0 |  |0 |                    |0 |
  709.   |--|  |--|  |--|  |--|  |--|              |--|
  710. 4 |  |  |  |  |  |  |  |  |1 |   1          |1 |
  711.   |--|  |--|  |--|  |--|  |--|  |--|        |--|
  712. 5                   |1 |  |  |  |4 |   4    |4 |
  713.                     |--|  |--|  |--|  |--|  |--|
  714.  
  715.  
  716. ---------------------------------------------------------------------------
  717. Now that you understand the algorithm 8^), we go back to parsort_table.  
  718. At the start of each call to thread_sort(), we need to find all the
  719. children of root_index.  We can do this quickly by using a sorted
  720. version of parent_table, called parsort_table.  It contains a
  721. convenient ordered list of children for us:
  722.  
  723.   x -+
  724.   x  | all the children of 'x' 
  725.   x  |                   
  726.   x -+                        
  727.   y -+            
  728.   y -+ all the children of 'y'
  729.   z -+
  730.   z  |
  731.   z  | all the children of 'z' 
  732.   z  | 
  733.   z -+
  734.  
  735. A single call (order logn) to bsearch_parsort_table puts us at the
  736. correct index for finding all the children we are looking for.
  737.  
  738. parsort_table
  739.   |--|
  740. 0 |1 |
  741.   |--|
  742. 1 |5 | 
  743.   |--|
  744. 2 |4 |
  745.   |--|
  746. 3 |3 |
  747.   |--|
  748. 4 |0 |
  749.   |--|
  750. 5 |2 |
  751.   |--|
  752.  
  753. ---------------------------------------------------------------------------
  754.  
  755. */@
  756.  
  757.  
  758. 1.8
  759. log
  760. @Documented the thread sort algorithm.
  761. @
  762. text
  763. @d4 1
  764. a4 1
  765.  * $Id: headarry.c 1.7 1993/12/08 01:27:21 rushing Exp rushing $
  766. d6 3
  767. d36 1
  768. d39 1
  769. @
  770.  
  771.  
  772. 1.7
  773. log
  774. @new version box and cr lf consistency
  775. @
  776. text
  777. @d4 5
  778. a8 2
  779.  * $Id: headarry.c 1.6 1993/06/25 20:44:45 dumoulin Exp rushing $
  780.  * $Log: headarry.c $ *
  781. a35 1
  782.  
  783. a390 1
  784. // long i;
  785. a397 8
  786. //
  787. //    for (i = 0; i < g_length; i++) {
  788. //      if (g_parent[g_length-i-1] == root_index) {
  789. //    g_index[end-num_children-1] = g_length-i-1;
  790. //    num_children++;
  791. //      }
  792. //    }
  793. //#endif
  794. d400 4
  795. a403 1
  796.     child_start = bsearch_parsort_table (g_parsort, g_parent, root_index, g_length);
  797. d503 184
  798. @
  799.  
  800.  
  801. 1.6
  802. log
  803. @Change dates from strings to Posix standard date formats
  804. @
  805. text
  806. @d1 1
  807. d4 6
  808. a10 4
  809.  * routines for handling the array of header information
  810.  * 
  811.  * $Id: headarry.c 1.5 1993/06/10 18:29:34 rushing Exp dumoulin $
  812.  * $Log: headarry.c $
  813. @
  814.  
  815.  
  816. 1.5
  817. log
  818. @added set_index_to_identity to prepare for writing article ranges
  819. @
  820. text
  821. @d6 1
  822. a6 1
  823.  * $Id: headarry.c 1.4 1993/06/08 19:41:56 rushing Exp rushing $
  824. d8 3
  825. d148 1
  826. a148 1
  827.     headers[i].date[0] = (char) 0;
  828. d233 9
  829. a241 1
  830.   return stricmp (headers[elem1].date , headers[elem2].date);
  831. d385 2
  832. a386 2
  833.  
  834.   long i,j;
  835. d394 8
  836. a401 8
  837. #if 0
  838.     for (i = 0; i < g_length; i++) {
  839.       if (g_parent[g_length-i-1] == root_index) {
  840.     g_index[end-num_children-1] = g_length-i-1;
  841.     num_children++;
  842.       }
  843.     }
  844. #endif
  845. @
  846.  
  847.  
  848. 1.4
  849. log
  850. @changes to support Sort... menu
  851. @
  852. text
  853. @d6 1
  854. a6 1
  855.  * $Id: headarry.c 1.3 1993/06/05 03:18:25 rushing Exp SOMEONE $
  856. d8 3
  857. d94 21
  858. @
  859.  
  860.  
  861. 1.3
  862. log
  863. @primitive functional threading.
  864. @
  865. text
  866. @d6 1
  867. a6 1
  868.  * $Id: headarry.c 1.2 1993/06/04 16:46:44 rushing Exp rushing $
  869. d8 3
  870. d46 1
  871. a46 1
  872. thread_array g_index, g_parent;
  873. d119 1
  874. d164 15
  875. d192 8
  876. a199 1
  877.   return strcmp (headers[elem1].subject , headers[elem2].subject);
  878. a201 1
  879.   
  880. a203 1
  881.           thread_array index,
  882. d206 1
  883. a206 1
  884.   return strcmp (headers[elem1].date , headers[elem2].date);
  885. d257 66
  886. d353 1
  887. d359 1
  888. d366 18
  889. a383 1
  890.     
  891. a444 1
  892. /*    sprintf (headers[i].from, "%3.3ld m%3.3ld p%3.3ld", i,mid_table[i],parent_table[i]); */
  893. d447 10
  894. d460 1
  895. a461 4
  896.  
  897.   /* clear it so we can debug */
  898.   for (i=0 ; i< length; i++)
  899.     g_index[i]=0;
  900. @
  901.  
  902.  
  903. 1.2
  904. log
  905. @stable version of shellsort
  906. @
  907. text
  908. @d6 1
  909. a6 1
  910.  * $Id: headarry.c 1.1 1993/06/01 18:15:12 rushing Exp rushing $
  911. d8 3
  912. d41 4
  913. d233 67
  914. d303 1
  915. d305 3
  916. a307 2
  917.   thread_array thread_index;
  918.  
  919. d311 2
  920. a312 3
  921.   if (thread_index) {
  922.  
  923.     shell_sort_index_array (headers, thread_index, length, compare_subject); 
  924. d314 8
  925. d323 7
  926. a329 1
  927. }
  928. d331 7
  929. d339 8
  930. d348 1
  931. d350 3
  932. a352 2
  933.  
  934.  
  935. @
  936.  
  937.  
  938. 1.1
  939. log
  940. @Initial revision
  941. @
  942. text
  943. @d2 1
  944. d6 4
  945. a9 2
  946.  * $Id:$
  947.  * $Log:$
  948. d11 1
  949. d38 1
  950. d137 44
  951. d182 43
  952. a228 1
  953.   long i;
  954. d236 2
  955. a237 4
  956.     
  957.     /* let's try reversing the array */
  958.     for (i=0; i <length ; i++)
  959.       thread_index[i] = (length - (i+1));
  960. d241 7
  961. @
  962.